
// IP Address checking stuff
// requires ra_client.js

var proplist		 	= new PropList();	// for IP Address validation
var validMulticastRange = new IPRange( new IPAddress('224.0.0.0') , new IPAddress('239.255.255.255') );

// raise base number to exponent function
function exp( base , exponent )
{
	if ( exponent == 0 )
		return 1;

	// don't support negative exponents
	if ( exponent < 0  )
		return 0;

	return base * exp( base , exponent - 1 );
}

// create an ip address range from a string
// create an ip address range from a string
function stringToIPRange( str ) 
{
	var tmp = new Object;
	var addrs = new Array();
	addrs = str.split('-');

	if ( addrs.length != 2 ) {
		tmp.errMsg = "IP地址必须在以下范围 [0-255].[0-255].[0-255].[0-255]-[0-255].[0-255].[0-255].[0-255].";
		return tmp;
	}

	if ( ! ( proplist.ip_validate( addrs[0] ) ) && ( proplist.ip_validate( addrs[1] ) ) ) {
		tmp.errMsg = proplist.errMsg;
		return tmp;
	}

	return new IPRange( new IPAddress( addrs[0] ) , new IPAddress( addrs[1] ) );
}

// ip address range constructor
function IPRange( addr1 , addr2, isMulticast )
{
	// test to make sure we're working with IPAddress objects
	if ( addr1.type && addr2.type && addr1.type == 'IPAddress' && addr2.type == 'IPAddress')
	{
		if ( addr1.addr > addr2.addr )
		{
			this.addressLow  = addr2;
			this.addressHigh = addr1;
		} 
		else
		{
			this.addressLow	 = addr1;
			this.addressHigh = addr2;
		}
	}
	else
	{
		this.errMsg = "错误的IP地址参数."
	}

	return this;
}

IPRange.prototype.toString = function ( )
{
	return this.addressLow.toString() + '-' + this.addressHigh.toString();
}

IPRange.prototype.addressInRange = function ( addr )
{
	return addr.isInRange( this );
}

IPRange.prototype.isOverlap = function ( range )
{
	return range.addressHigh.isInRange( this ) || range.addressLow.isInRange( this ) || this.addressHigh.isInRange( range ) || this.addressLow.isInRange( range );
}

IPRange.prototype.isSubset = function ( range )
{
	return this.addressHigh.isInRange( range ) && this.addressLow.isInRange( range );
}

IPRange.prototype.numAddrsInRange = function ( )
{
	return this.addressHigh.addr - this.addressLow.addr + 1;
}

function IPAddress( addr, isMulticast )
{
	if ( ! proplist.ip_validate( addr ) ) {
		this.errMsg = proplist.errMsg;
		return this;
	}

	var octets	= addr.split('.');
	if ( octets.length < 4 )
	{
		// assure we've got at least 4 octets
		octets.push( 0, 0, 0, 0 );
	}

	this.addr = eval(octets[0] * 16777216) + eval(octets[1] * 65536) + eval(octets[2] * 256) + eval(octets[3]);

	this.type = 'IPAddress';
	return this;
}

IPAddress.prototype.toString = function ( ) 
{
	var str = "";
	for ( var i = 0; i < 4; i++ ) {
		str += ( this.addr & ( 255 << ( 3 - i ) * 8 ) ) >>> ( 3 - i ) * 8;
		str += '.';
	}

	// return string without the trailing '.'
	return str.substr(0 , str.length - 1 );
}

IPAddress.prototype.isBetween = function ( compareIP1 , compareIP2 )
{
	var range = new IPRange( compareIP1 , compareIP2 );
	return this.isInRange( range );
}

IPAddress.prototype.isInRange = function ( range )
{
	return (this.addr < range.addressHigh.addr && this.addr > range.addressLow.addr) || ( this.addr == range.addressLow.addr || this.addr == range.addressHigh.addr );
}

IPAddress.prototype.isClassD = function ()
{
	return (this.addr >= 3758096384) && (this.addr < 4026531840);
}

IPAddress.prototype.isClassC = function ()
{
	return (this.addr >= 3221225472) && (this.addr < 3758096384);
}

function AddressRangeCtrl ( name, minRange, isRequired, isNotMulticast )
{
	this.m_name = (name ? name : "AddressRange");
	this.m_minRange = (minRange != null ? minRange : 0);
	this.m_isRequired = (isRequired != null ? isRequired : true);
	this.m_isMulticast = ( isNotMulticast ? false : true );

	this.m_addr1 = this.m_name + "1";
	this.m_addr2 = this.m_name + "2";
}

AddressRangeCtrl.prototype.fillForm = function ( oForm )
{
	if ( oForm && 
		 oForm[ this.m_name ] && 
		 oForm[ this.m_addr1 ] && 
		 oForm[ this.m_addr2 ] )
	{
		// split AddressRange into lower and upper display fields
		var aTemp = getCtrlValue( oForm[ this.m_name ] ).split( /\s*-\s*/ );
		setCtrlValue( oForm[ this.m_addr1 ], (aTemp[0] ? aTemp[0] : ""), true );
		setCtrlValue( oForm[ this.m_addr2 ], (aTemp[1] ? aTemp[1] : ""), true );
	}	
}

AddressRangeCtrl.prototype.validate = function ( oForm )
{
	if ( oForm && 
		 oForm[ this.m_name ] && 
		 oForm[ this.m_addr1 ] && 
		 oForm[ this.m_addr2 ] )
	{
		var addr1 = getCtrlValue( oForm[ this.m_addr1 ] );
		var addr2 = getCtrlValue( oForm[ this.m_addr2 ] );

		// both pieces missing?
		if ( isBlank( addr1 ) && isBlank( addr2 ) )
		{
			if ( this.m_isRequired )
			{
				return rejectInput( oForm[ this.m_addr1 ], 
					"An Address Range is required." );
			}
			else
			{
				setCtrlValue( oForm[ this.m_name ], "" );
				return true;
			}
		}

		// one piece missing?
		if ( isBlank( addr1 ) || isBlank( addr2 ) )
		{
			if ( 0 != this.m_minRange )
			{
				return rejectInput( oForm[ this.m_addr1 ], 
					"无效的IP地址范围, 有效的IP地址范围必须至少包含" +
					 (this.m_minRange+1) + " 个地址".pluralize(this.m_minRange+1) + "." );
			}

			if ( isBlank( addr1 ) )
			{
				addr1 = addr2;
			}
			else
			{
				addr2 = addr1;
			}
			setCtrlValue( oForm[ this.m_addr1 ], addr1 );
			setCtrlValue( oForm[ this.m_addr2 ], addr1 );
		}

		var err = getIPAddrErr( addr1, this.m_isMulticast );
		if ( err )
			return rejectInput( oForm[ this.m_addr1 ], err );

		err = getIPAddrErr( addr2, this.m_isMulticast );
		if ( err )
			return rejectInput( oForm[ this.m_addr2 ], err );

		// convert to IPAddress objects and compare 
		var oAddr1 = new IPAddress( addr1 );
		var oAddr2 = new IPAddress( addr2 );

		if ( oAddr1.addr > oAddr2.addr )
		{
			// user must be lesydexic, give em a break
			var tmp = addr1;
			addr1 = addr2;
			addr2 = tmp;

			setCtrlValue( oForm[ this.m_addr1 ], addr1 );
			setCtrlValue( oForm[ this.m_addr2 ], addr2 );
		}

		if ( Math.abs(oAddr1.addr - oAddr2.addr) < this.m_minRange )
		{
			return rejectInput( oForm[ this.m_addr1 ], 
				"无效的IP地址范围, 有效的IP地址范围必须至少包含 " +
				 (this.m_minRange+1) + " 个地址".pluralize(this.m_minRange+1) + "." );
		}

		// combine into AddressRange field
		setCtrlValue( oForm[ this.m_name ], addr1 + "-" + addr2, true );

		return true ;
	}
}

function getIPAddrErr ( addr, isMulticast )
{
	var errMsg = "";

	var isValid = isIPAddr( addr );
	if ( isValid && isMulticast )
	{
		isValid = (new IPAddress( addr ).isClassD());
	}

	if ( ! isValid )
	{
		if ( isMulticast )
		{
			errMsg = "'" + addr + "' 是一个无效的多播IP地址. 多播IP地址必须在以下范围 " + 
				"224.0.0.0 to 239.255.255.255" ;
		}
		else
		{
			errMsg =  "'" + addr + "' 是一个无效的IP地址. IP地址必须在以下范围 [1-255].[0-255].[0-255].[0-255]";
		}
	}

	return errMsg;
}

